import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { CSS3DRenderer } from "three/addons/renderers/CSS3DRenderer.js";
import { CSS2DRenderer } from "three/addons/renderers/CSS2DRenderer.js";
import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";
import { RenderPass } from "three/addons/postprocessing/RenderPass.js";
import { OutlinePass } from "three/addons/postprocessing/OutlinePass.js";
import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js";
import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js";
import { SMAAPass } from "three/addons/postprocessing/SMAAPass.js";
import { FXAAShader } from "three/addons/shaders/FXAAShader.js";
import { Reflector } from "three/addons/objects/Reflector.js";

let scene, camera, controls, renderer, css3DRenderer, css2DRenderer, outlinePass, composer, bloomPass, finalComposer, mirror;

function initScene(width, height) {
  // 场景
  scene = new THREE.Scene();
  scene.fog = new THREE.FogExp2("#000", 0.0015);
  scene.background = new THREE.Color("#011024");
  // scene.background = null;

  const geometry = new THREE.PlaneGeometry(600, 600);
  mirror = new Reflector(geometry, {
    clipBias: 0.003,
    textureWidth: width * window.devicePixelRatio,
    textureHeight: height * window.devicePixelRatio,
    color: "#fff",
  });
  mirror.position.y = -10.1;
  mirror.rotateX(-Math.PI / 2);

  // 灯光
  const ambientLight = new THREE.AmbientLight(0xffffff, 5);
  scene.add(ambientLight);

  const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
  directionalLight.position.set(200, 100, 200);
  scene.add(directionalLight);

  // 相机
  camera = new THREE.PerspectiveCamera(30, width / height, 1, 10000);
  camera.position.set(0, 9000, 7000);
  camera.lookAt(0, 0, 0);

  // 渲染器
  renderer = new THREE.WebGLRenderer({
    antialias: true,
    alpha: true,
  });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(width, height);
  renderer.setClearColor("#000");

  // CSS3D渲染器
  css3DRenderer = new CSS3DRenderer();
  css3DRenderer.setSize(width, height);
  css3DRenderer.domElement.style.position = "absolute";
  css3DRenderer.domElement.style.top = "0px";
  css3DRenderer.domElement.style.pointerEvents = "none";

  // CSS2D渲染器
  css2DRenderer = new CSS2DRenderer();
  css2DRenderer.setSize(width, height);
  css2DRenderer.domElement.style.position = "absolute";
  css2DRenderer.domElement.style.top = "0px";
  css2DRenderer.domElement.style.pointerEvents = "none";

  // 后处理器
  composer = new EffectComposer(renderer);
  composer.renderToScreen = false;
  const renderPass = new RenderPass(scene, camera);
  composer.addPass(renderPass);

  // OutlinePass通道
  outlinePass = new OutlinePass(new THREE.Vector2(width, height), scene, camera);
  outlinePass.visibleEdgeColor.set("#00FFFF");
  outlinePass.edgeThickness = 1.5;
  outlinePass.edgeStrength = 3;
  composer.addPass(outlinePass);

  // UnrealBloomPass通道
  bloomPass = new UnrealBloomPass(new THREE.Vector2(width, height));
  bloomPass.threshold = 0;
  bloomPass.strength = 0;
  bloomPass.radius = 0;
  bloomPass.renderToScreen = false;

  // 着色器通道
  const shaderPass = new ShaderPass(
    new THREE.ShaderMaterial({
      uniforms: {
        baseTexture: { value: null },
        bloomTexture: { value: composer.renderTarget2.texture },
        tDiffuse: {
          value: null,
        },
      },
      vertexShader:
        "\t\t\tvarying vec2 vUv;\n" +
        "\n" +
        "\t\t\tvoid main() {\n" +
        "\n" +
        "\t\t\t\tvUv = uv;\n" +
        "\n" +
        "\t\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n" +
        "\n" +
        "\t\t\t}",
      fragmentShader:
        "\t\t\tuniform sampler2D baseTexture;\n" +
        "\t\t\tuniform sampler2D bloomTexture;\n" +
        "\n" +
        "\t\t\tvarying vec2 vUv;\n" +
        "\n" +
        "\t\t\tvoid main() {\n" +
        "\n" +
        "\t\t\t\tgl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) );\n" +
        "\n" +
        "\t\t\t}",
      defines: {},
    }),
    "baseTexture"
  );
  shaderPass.renderToScreen = true;
  shaderPass.needsSwap = true;

  // 最终合成器
  finalComposer = new EffectComposer(renderer);
  finalComposer.addPass(renderPass);
  finalComposer.addPass(shaderPass);

  // SMAAPass抗锯齿通道
  const pixelRatio = renderer.getPixelRatio();
  const smaaPass = new SMAAPass(width * pixelRatio, height * pixelRatio);
  finalComposer.addPass(smaaPass);

  const FXAAPass = new ShaderPass(FXAAShader);
  FXAAPass.uniforms.resolution.value.x = 1 / (width * pixelRatio);
  FXAAPass.uniforms.resolution.value.y = 1 / (height * pixelRatio);
  finalComposer.addPass(FXAAPass);

  // 相机轨道控制器
  controls = new OrbitControls(camera, renderer.domElement);
  controls.dampingFactor = 0.1;
  controls.enableDamping = true;
  controls.minPolarAngle = -Math.PI;
  controls.maxPolarAngle = Math.PI / 2.5;
  controls.minDistance = 80;
  controls.maxDistance = 1000;

  // 画布跟随窗口变化
  window.addEventListener("resize", () => {
    const width = window.innerWidth;
    const height = window.innerHeight;
    renderer.setSize(width, height);
    camera.aspect = width / height;
    camera.updateProjectionMatrix();
    css3DRenderer.setSize(width, height);
    css2DRenderer.setSize(width, height);
  });
}

export { scene, camera, controls, renderer, css3DRenderer, css2DRenderer, outlinePass, composer, bloomPass, finalComposer, mirror, initScene };
